﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

#pragma once
#include "GcmpUiBase.h"
#include <QtCore/QObject>

namespace gnuf {
/*
[ Diagram ]
    
    Main                    +---------------+
    Thread                  | Child Thread   \
                            .                 +- - - - - - - - -+
                            |                _______________    |
    +-----------+           .               //             \\   .
    |           |   Start   |               |               |   |
    |          ============================>>>           Qt |   .
    |           |           |         Run   |        Worker |   |
    | Worker   <<<============================       Thread |   .
    | Thread    |           |               |               |   |
    |           | <~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~|               |   .
    +-----------+           |   Debug Warn  |               |   |
                            .               \\_____________//   .
                            +- - - - - - - - - - - - - - - - - -+
    
[ Illustration ]

    " <<<===== " Call a Main-Thread's method, inside of the Child-Thread.
    " =====>>> " Call a Child-Thread's method, inside of the Main-Thread.
    " <~ ~ ~ ~ " Emit a Qt signal, from the Child-Thread to the Main-Thread.
*/
    
    class QtWorkerThread;
    
    class GCMP_UIBASE_EXPORT WorkerThread : public QObject
    {
        Q_OBJECT
        
    public:
        typedef std::function< void() > Work;
        
        WorkerThread();
        WorkerThread(const WorkerThread::Work &);
        virtual ~WorkerThread();
        
        /// \brief Give the worker a work (a callback) that is invoked later.
        void setWork(const WorkerThread::Work & work) { m_work = work; }
        /// \return Return the work.
        const WorkerThread::Work & work() { return m_work; }

        /// \return Return true during working.
        bool isWorking() const { return m_working; }
        
        /// \brief Execute not until finished.
        bool exec();
        
    protected:
        // Let the derived class work.
        virtual void onWork() {}
        // Let the derived class know that the work finished.
        virtual void onWorkFinished() {}

        // Start the thread.
        bool start();

    private slots:
        void onFinished();
        bool onDebugWarnOutsideOf(
            const QtWorkerThread *,
            const std::wstring & text,
            const std::wstring & name,
            const std::wstring & data);

    private:
        void initialize();

        friend class QtWorkerThread;
        void runInsideOf(const QtWorkerThread * pChildThread);

        QtWorkerThread * m_qtWorkerThread;
        WorkerThread::Work m_work;
        bool m_working;
    };
}
